/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.analysisModel;

import java.io.Serializable;
import java.util.ArrayList;

import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IVector;
import br.ufmg.dees.insane.util.geometricProperties.GeometricProperties;
import br.ufmg.dees.insane.util.pointValues.PointValues;
import br.ufmg.dees.insane.util.pointValues.StringPointValues;

/** A class representing analysis model referring to the
 *  elements of Reissner-Mindlin Plate
 * @author Samir
 * @since 18/05/2006
 */
public class ReissnerMindlinPlate implements AnalysisModel, Serializable {
	
	private static final long serialVersionUID = 1L;
	/**Constructs a ReissnerMindlinPlate AnalysisModel.*/
    public ReissnerMindlinPlate(){    	
	}
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getType()
     */
   public String getLabel() {
        return "ReissnerMindlinPlate";
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IVector n, IMatrix c){
        int nNos = d.getNumCol();
        IMatrix dG = new IMatrix(2, d.getNumCol());
        IMatrix b = new IMatrix(5, (3*nNos));
        dG.setZero();
        b.setZero();
        IMatrix J1 = this.invertJacobian(this.getJacobian(d, c));
        dG.mul(J1,d);
        int j = 0;
        int k = 0;
        for(int i = 0; i < nNos; i++){
        	j++;
            b.setElement(0, j, dG.getElement(0, i));
            b.setElement(1, (j+1), dG.getElement(1, i));
            b.setElement(2, j, dG.getElement(1, i));
            b.setElement(2, (j+1), dG.getElement(0, i));
            b.setElement(3, k, -dG.getElement(0, i));
            b.setElement(3, j, n.getElement(i));
            b.setElement(4, k, -dG.getElement(1, i));
            b.setElement(4, (j+1), n.getElement(i));
            j = j + 2;
            k = k + 3;
        }
        return(b);
    }

    /* (non-Javadoc)
     * @see lr.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVarialleOperator(lr.ufmg.dees.insane.util.IMatrix, lr.ufmg.dees.insane.util.IVector, lr.ufmg.dees.insane.util.IMatrix, lr.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IVector n, IMatrix c, IMatrix u) {
        int nNos = d.getNumCol();
        IMatrix dG = new IMatrix(2, d.getNumCol());
        IMatrix b = new IMatrix(5, (3*nNos));
        dG.setZero();
        b.setZero();
        IMatrix J1 = this.invertJacobian(this.getJacobian(d, c));
        dG.mul(J1,d);
        int j = 0;
        int k = 0;
        for(int i = 0; i < nNos; i++){
        	j++;
            b.setElement(0, j, dG.getElement(0, i));
            b.setElement(1, (j+1), dG.getElement(1, i));
            b.setElement(2, j, dG.getElement(1, i));
            b.setElement(2, (j+1), dG.getElement(0, i));
            b.setElement(3, k, -dG.getElement(0, i));
            b.setElement(3, j, n.getElement(i));
            b.setElement(4, k, -dG.getElement(1, i));
            b.setElement(4, (j+1), n.getElement(i));
            j = j + 2;
            k = k + 3;
        }
        return(b);
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getShapeMatrix(br.ufmg.dees.insane.util.IVector)
     */
    public IMatrix getStateVariableOperator(IMatrix d, IVector n, IMatrix c) {
    	int nNos = n.getSize();
        IMatrix matrixN = new IMatrix(3, (3*nNos));
        matrixN.setZero();
        for(int i = 0; i < nNos; i++)
        {
            for(int j = 0; j < 3; j++)
            {
                matrixN.setElement(j, (3*i)+j, (n.getElement(i)));
            }
        }
        return matrixN;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getIntegrationFactor(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
    public double getIntegrationFactor(IVector n, IMatrix cN, GeometricProperties gps) {
    	return 1;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getDominion()
     */
    public int getDominion() {
        return 2; 
    }
    
    /* (non-Javadoc)
	 * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getGeometricOperator(br.ufmg.dees.insane.util.IVector)
	 */
    public IMatrix getGeometricOperator(IVector n1) {
    	IMatrix n = new IMatrix(3, 2*n1.getSize());
    	n.setZero();
    	for(int i = 0; i < n1.getSize(); i++){
    		n.setElement(0, (i*2), n1.getElement(i));
    		n.setElement(1, ((i*2)+1), n1.getElement(i));
    	}
		return n;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getDualInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getDualInternalVariableOperator(IMatrix e){
    	IMatrix d = new IMatrix(5,5);
		d.setZero();
		double Ex = e.getElement(0,0);
		double Ey = e.getElement(1,1);
		double vxy = e.getElement(0,1);
		double vyx = e.getElement(1,0);
		double Gxy = e.getElement(3,3);
		double Gxz = e.getElement(4,4);
		double Gyz = e.getElement(5,5);
		double k = (1/(1-(vxy*vyx)));
		
		d.setElement(0,0,(k*Ex));
		d.setElement(0,1,(k*vxy*Ex));
		d.setElement(1,0,(k*vyx*Ex));
		d.setElement(1,1,(k*Ey));
		d.setElement(2,2,(k*(1-(vyx*vxy))*Gxy));
		
		d.setElement(3,3,(5*Gxz/6));
		d.setElement(4,4,(5*Gyz/6));
		return(d); 
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getDualInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix)
     */
	public IMatrix modifyDualInternalVariableOperator(IMatrix e, GeometricProperties gps){
		double t = gps.getThickness();
		double cf = t*t/12;
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				e.setElement(i,j,e.getElement(i,j)*t);
			}
		}
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				e.setElement(i,j,e.getElement(i,j)*cf);
			}
		}
		return e;
	}
	
	/* (non-Javadoc)
	 * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#modifyDualInternalVariableVector(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.geometricProperties.GeometricProperties)
	 */
	public IVector modifyDualInternalVariableVector(IVector s, GeometricProperties gps) {
		double t = gps.getThickness();
		double cf = t*t/12;
		for (int i = 0; i < 5; i++) {
				s.setElement(i,s.getElement(i)*t);
			}
		for (int i = 0; i < 3; i++) {
				s.setElement(i,s.getElement(i)*cf);
		}
		return s;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getNumberOfInternalVariables()
     */
    public int getNumberOfInternalVariables(){
    	return 5; 
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getNumberOfDualInternalVariables()
     */
    public int getNumberOfDualInternalVariables(){
    	return 5; 
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVariablesTensor(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
     public IMatrix getInternalVariablesTensor(IVector a, IMatrix b){
         return expandTensor(a);	
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalDualVariablesTensor(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getDualInternalVariablesTensor(IVector a, IMatrix b){
        return expandTensor(a);
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVariablesDirLabels()
     */
    public String[] getInternalVariablesLabels() {
        String[] Dlabels = {"Wxx", "Wyy", "2Wxy", "GAMAxz", "GAMAyz"};
        return Dlabels;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getDualInternalVariablesDirLabels()
     */
    public String[] getDualInternalVariablesLabels() {
        String[] Dlabels = {"Mxx", "Myy", "Mxy", "Qxz", "Qyz"};
        return Dlabels;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#expandVector(br.ufmg.dees.insane.util.IVector)
     */
    public IVector expandVector(IVector a){
    	IVector Vector = new IVector(6);
        Vector.setElement(0,a.getElement(0));
        Vector.setElement(1,a.getElement(1));
        Vector.setElement(2,a.getElement(2));
        Vector.setElement(3,a.getElement(3));
        Vector.setElement(4,a.getElement(4));
        return Vector;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#expandTensor(br.ufmg.dees.insane.util.IVector)
     */
    public IMatrix expandTensor(IVector a){
    	IMatrix Tensor = new IMatrix(3,3);
    	Tensor.setZero();
        Tensor.setElement(0,0,a.getElement(0));
        Tensor.setElement(0,1,a.getElement(2));
        Tensor.setElement(0,2,a.getElement(3));
        Tensor.setElement(1,0,a.getElement(2));
        Tensor.setElement(1,1,a.getElement(1));
        Tensor.setElement(1,2,a.getElement(4));
        Tensor.setElement(2,0,a.getElement(3));
        Tensor.setElement(2,1,a.getElement(4));
        return Tensor;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#reduceVector(br.ufmg.dees.insane.util.IVector)
     */
    public IVector reduceVector(IVector a){
    	IVector Vector = new IVector(5);
        Vector.setElement(0,a.getElement(0));
        Vector.setElement(1,a.getElement(1));
        Vector.setElement(2,a.getElement(2));
        Vector.setElement(3,a.getElement(3));
        Vector.setElement(4,a.getElement(4));
        return Vector;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#reduceTensor(br.ufmg.dees.insane.util.IMatrix)
     */
    public IVector reduceTensor(IMatrix a){
    	IVector Vector = new IVector(5);
        Vector.setElement(0,a.getElement(0,0));
        Vector.setElement(1,a.getElement(1,1));
        Vector.setElement(2,a.getElement(0,1));
        Vector.setElement(3,a.getElement(0,2));
        Vector.setElement(4,a.getElement(1,2));
        return Vector;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getJacobianTransformation(br.ufmg.dees.insane.util.IMatrix)
     */
    public double getJacobianTransformation(IMatrix dl, IMatrix cN)	
    {
        IMatrix jacobian = new IMatrix(this.getDominion(),this.getDominion());
        jacobian.setZero();
        jacobian.mul(dl, cN);
        double detJ = jacobian.determinantLU();
        return(detJ);
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getTransformationMatrix(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getTransformationMatrix(IMatrix dl, IMatrix cN) {
    	IMatrix transf = new IMatrix(dl.getNumCol()*3,dl.getNumCol()*3);
    	transf.setIdentity();
        return transf;
    }

    /** Return the jacobian matrix.
	*@param dl The matrix of local derivates.
	*@param cN The matrix of nodal coordinates.
	*@return dl * cN The jacobian matrix.
	*/
	private IMatrix getJacobian(IMatrix dl, IMatrix cN)
	{
		IMatrix jacobian = new IMatrix(this.getDominion(),this.getDominion());
		jacobian.setZero();
		jacobian.mul(dl, cN);
		return(jacobian);
	}
    
    /** Return the inverse of jacobian matrix.
    *@param a The jacobian matrix.
    *@return the inverse of jacobian matrix.
    */
    public IMatrix invertJacobian(IMatrix a)
    {
        IMatrix b = new IMatrix(2,2);
        b.setZero();
        b.setElement(0,0,a.getElement(1,1));
        b.setElement(0,1,((-1)*(a.getElement(1,0))));
        b.setElement(1,0,((-1)*(a.getElement(0,1))));
        b.setElement(1,1,a.getElement(0,0));
        b.transpose();
        b.setScale(1/a.determinantLU());
        return (b);
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getJ2(br.ufmg.dees.insane.util.IMatrix)
     */
	public double getJ2(IVector s) {
		// TODO Auto-generated method stub
		return 0;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getdJ2dSIG(br.ufmg.dees.insane.util.IMatrix)
     */
	public IVector getdJ2dSIG(IVector s) {
		// TODO Auto-generated method stub
		return null;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getJ3(br.ufmg.dees.insane.util.IMatrix)
     */
	public double getJ3(IVector s) {
		// TODO Auto-generated method stub
		return 0;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getdJ3dSIG(br.ufmg.dees.insane.util.IMatrix)
     */
	public IVector getdJ3dSIG(IVector s) {
		// TODO Auto-generated method stub
		return null;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getI1(br.ufmg.dees.insane.util.IMatrix)
     */
	public double getI1(IVector s) {
		// TODO Auto-generated method stub
		return 0;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getdI1dSIG(br.ufmg.dees.insane.util.IMatrix)
     */
	public IVector getdI1dSIG(IVector s) {
		// TODO Auto-generated method stub
		return null;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getI2(br.ufmg.dees.insane.util.IMatrix)
     */
	public double getI2(IVector s) {
		// TODO Auto-generated method stub
		return 0;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getdI2dSIG(br.ufmg.dees.insane.util.IMatrix)
     */
	public IVector getdI2dSIG(IVector s) {
		// TODO Auto-generated method stub
		return null;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getI3(br.ufmg.dees.insane.util.IMatrix)
     */
	public double getI3(IVector s) {
		// TODO Auto-generated method stub
		return 0;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getdI3dSIG(br.ufmg.dees.insane.util.IMatrix)
     */
	public IVector getdI3dSIG(IVector s) {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#modifyInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IMatrix)
	 */
	public IMatrix modifyInternalVariableOperator(IMatrix e, IMatrix p) {
		return e;
	}
	
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#ggetDOFLabels(int)
     */
	public ArrayList getDOFLabels(int n){
		ArrayList <PointValues> al = new ArrayList<PointValues>();
		PointValues spv = new StringPointValues();
	    spv.addPointValue("Dz");
	    spv.addPointValue("Rx");
	    spv.addPointValue("Ry");
		for(int i=0; i<n; i++) {
			al.add(i,spv);
		}
		return al;
	}

	public ArrayList getDOFLabels() {
		// TODO Auto-generated method stub
		return null;
	}

	public IMatrix getPMatrix() {
		// TODO Auto-generated method stub
		return null;
	}
}
